<!-- eslint-disable @typescript-eslint/no-explicit-any -->
<!-- eslint-disable vue/no-mutating-props -->
<script lang="ts">
import { defineComponent, h, inject, markRaw, onMounted, PropType, ref, toRefs, watch } from "vue";
import { IDynamicFormItem } from "../DynamicForm";
import BaseCheckVue from "../DynamicFormItemControls/BaseCheck.vue";
import BaseDivider from "../DynamicFormItemControls/BaseDivider.vue";
import BaseInputVue from "../DynamicFormItemControls/BaseInput.vue";
import BaseRadio from "../DynamicFormItemControls/BaseRadio.vue";
import BaseSelectVue from "../DynamicFormItemControls/BaseSelect.vue";
import BaseTextAreaVue from "../DynamicFormItemControls/BaseTextArea.vue";
import { DynamicFormItemRegistry, DynamicFormItemRegistryItem } from "./DynamicFormItemRegistry";

let registeredInternal = false;

export interface DynamicFormItemRendererInterface {
  getRef: () => unknown,
}
/**
 * 动态表单条目渲染组件。
 */
export default defineComponent({
  props: {
    item: {
      type: Object as PropType<IDynamicFormItem>,
    },
    disabled: {
      type: Boolean
    },
    parentModel: {
    },
    value: {
    },
    name: {
      type: String
    },
    additionalProps: {
      type: Object as PropType<Record<string, unknown>>,
    },
  },
  emits: [ 
    'update:value'
  ],
  setup(props, context) {
    const {
      item,
      additionalProps,
      disabled,
      parentModel,
      value,
      name,
    } = toRefs(props);

    const componentRef = ref();
    const componentInstance = ref(null as any);
    const componentAdditionalProps = ref(null as any);
    const componentValueName = ref(null as any);
    const componentOnUpdateValueName = ref(null as any);

    function getRef() {
      return componentRef.value;
    }
    function onUpdateValue(v: unknown) {
      context.emit('update:value', v);
    }
    function registerInternalDynamicFormItemControls() : void {
      //注册所有内置表单组件类型
      if (!registeredInternal) {
        registeredInternal = true;
        DynamicFormItemRegistry.registerDynamicFormItemControl('base-text', markRaw(BaseInputVue));
        DynamicFormItemRegistry.registerDynamicFormItemControl('base-select', markRaw(BaseSelectVue));
        DynamicFormItemRegistry.registerDynamicFormItemControl('base-textarea', markRaw(BaseTextAreaVue));
        DynamicFormItemRegistry.registerDynamicFormItemControl('base-check', markRaw(BaseCheckVue));
        DynamicFormItemRegistry.registerDynamicFormItemControl('base-radio', markRaw(BaseRadio));
        DynamicFormItemRegistry.registerDynamicFormItemControl('base-divider', markRaw(BaseDivider));
      }
    }
    function findComponent() {
      const itemValue = (item.value as IDynamicFormItem);

      if (!itemValue?.type) {
        componentInstance.value = null;
        return;
      }

      let type : DynamicFormItemRegistryItem|null = null;
      if (widgetOvrride)
        type = (widgetOvrride as Record<string, DynamicFormItemRegistryItem>)[itemValue.type];

      if (type == null)
        type = DynamicFormItemRegistry.findDynamicFormItemByType(itemValue.type);

      if (type == null) {
        componentInstance.value = null;
        return;
      }
      
      componentInstance.value = type.componentInstance;
      componentAdditionalProps.value = type.additionalProps;
      componentValueName.value = type.valueName;
      componentOnUpdateValueName.value = 'onUpdate:'+ type.valueName;
    }

    watch(item, () => {
      findComponent();
    });
    onMounted(() => {
      registerInternalDynamicFormItemControls();
      findComponent();
    });

    const rawModel = inject<Record<string, unknown>>('rawModel'); 
    const widgetOvrride = inject<Record<string, DynamicFormItemRegistryItem>>('widgetOvrride'); 

    context.expose({
      onUpdateValue,
      registerInternalDynamicFormItemControls,
      findComponent,
      getRef,
      rawModel,
      widgetOvrride,
      componentRef,
      componentInstance,
      componentAdditionalProps,
      componentValueName,
      componentOnUpdateValueName,
    });

    return () => {
      if (componentInstance.value) {
        return h(componentInstance.value, {
          ref: componentRef,
          ...(componentAdditionalProps.value as Record<string, unknown>),
          ...(additionalProps.value as Record<string, unknown>),
          disabled: disabled.value,
          item: item.value,
          rawModel: rawModel,
          parentModel: parentModel.value,
          name: name.value,
          ...(item.value?.additionalEvents),
          ...(item.value?.additionalDirectProps),
          //双向数据绑定属性
          [componentValueName.value]: value.value,
          [componentOnUpdateValueName.value]: (v: unknown) => onUpdateValue(v),
        });
        
      } else {
        return h('span', {
          class: 'dynamic-form-error-alert'
        }, `警告：未找到表单组件实例 ${(item.value as IDynamicFormItem)?.type || '未知'} ${JSON.stringify(widgetOvrride || {})}`);
      }
    }
  },
});

</script>